package de.tabiteuea.gui.wizards;

import java.io.IOException;

import javax.xml.stream.XMLStreamException;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.ISharedImages;

import de.tabiteuea.gui.dialogs.OpenFileDialog;
import de.tabiteuea.gui.models.InputModel;
import de.tabiteuea.gui.utils.ImageProvider;

/**
 * 
 * Page for NewProjectWizard.
 * <p>
 * Contains the implementation of the visual aspects and processes the user
 * input. At the end it creates a returnable InputModel.
 * <p>
 * The UI consists of two fields for project name and project file as well as
 * corresponding labels, buttons and of course listeners.
 * <p>
 * 
 * This page is only valid if a project name is set and a valid file is chosen.
 * 
 * @author Sebastian Lippert
 */

public class NewProjectWizardPage extends WizardPage {

	private Text projectName;
	private Text filePath;
	private Button openFileButton;
	private Composite parent;
	private InputModel model;

	/**
	 * Constructor
	 */

	protected NewProjectWizardPage() {

		// set title and set validation status to false, cause every field is
		// empty on start up
		super(Messages.NewProjectWizardPage_new);
		setTitle(Messages.NewProjectWizardPage_message);
		setErrorMessage(Messages.NewProjectWizardPage_error_noName);
		setPageComplete(false);
	}

	/**
	 * Visual creation of the page
	 */

	@Override
	public void createControl(final Composite parent) {

		this.parent = parent;

		Label label;
		GridData grid;
		GridLayout layout;

		// register decoration
		FieldDecorationRegistry fieldDecoReg = FieldDecorationRegistry
				.getDefault();
		final ControlDecoration nameDecoration;
		final ControlDecoration pathDecoration;
		final Image errorImage = fieldDecoReg.getFieldDecoration(
				FieldDecorationRegistry.DEC_ERROR).getImage();

		// main container
		Composite comp = new Composite(parent, SWT.NONE);
		comp.setLayout(new GridLayout(2, false));
		comp.setLayoutData(new GridData(GridData.FILL_BOTH));

		// field and label for project name
		label = new Label(comp, SWT.NONE);
		label.setText(Messages.NewProjectWizardPage_projectName);

		grid = new GridData(GridData.FILL_HORIZONTAL);
		grid.horizontalIndent = 20;

		projectName = new Text(comp, SWT.BORDER);
		projectName.setLayoutData(grid);

		nameDecoration = new ControlDecoration(projectName, SWT.TOP | SWT.LEFT);
		nameDecoration.setImage(errorImage);

		// listener validates the input and set the decoration of the project
		// name depending on the input
		projectName.addKeyListener(new KeyAdapter() {

			@Override
			public void keyReleased(KeyEvent e) {

				String text = projectName.getText().trim();

				// empty check
				if (!text.isEmpty()) {
					nameDecoration.setImage(null);

					// validation is false
					if (filePath.getText().trim().isEmpty())
						setErrorMessage(Messages.NewProjectWizardPage_error_noFile);
					else {
						// everything is fine, validation is true
						setErrorMessage(null);
						setPageComplete(true);
					}
				} else {
					// validation is false
					nameDecoration.setImage(errorImage);
					setErrorMessage(Messages.NewProjectWizardPage_error_noName);
					setPageComplete(false);
				}
			}
		});

		// field, button and label for project file
		label = new Label(comp, SWT.NONE);
		label.setText(Messages.NewProjectWizardPage_openFile);

		layout = new GridLayout(2, false);
		layout.marginLeft = -5;
		layout.marginRight = -5;

		Composite pathComp = new Composite(comp, SWT.NONE);
		pathComp.setLayout(layout);
		pathComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		grid = new GridData(GridData.FILL_HORIZONTAL);
		grid.horizontalIndent = 20;
		grid.grabExcessHorizontalSpace = true;

		filePath = new Text(pathComp, SWT.BORDER | SWT.READ_ONLY);
		filePath.setLayoutData(grid);

		pathDecoration = new ControlDecoration(filePath, SWT.TOP | SWT.LEFT);
		pathDecoration.setImage(errorImage);

		// listener validates the input and set the decoration of the project
		// file depending on the input
		filePath.addModifyListener(new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e) {

				String text = filePath.getText().trim();

				// empty check
				if (!text.isEmpty()) {
					pathDecoration.setImage(null);

					// validation is false
					if (projectName.getText().trim().isEmpty())
						setErrorMessage(Messages.NewProjectWizardPage_error_noName);
					else {
						// everything is fine, validation is true
						setErrorMessage(null);
						setPageComplete(true);
					}

				} else {
					// validation is false
					pathDecoration.setImage(errorImage);
					setPageComplete(false);
					setErrorMessage(Messages.NewProjectWizardPage_noFileOpened);
				}

			}
		});

		// button calls a dialog to open a file on the hard disk
		openFileButton = new Button(pathComp, SWT.PUSH);
		openFileButton.setImage(ImageProvider
				.getSharedImage(ISharedImages.IMG_OBJ_FOLDER));
		openFileButton
				.setToolTipText(Messages.NewProjectWizardPage_tool_openFile);

		// activate button Listeners
		hookButtonListeners();
		setControl(comp);
	}

	/*
	 * register listeners to the buttons
	 */

	private void hookButtonListeners() {

		// handle openFileButton
		openFileButton.addSelectionListener(new SelectionAdapter() {

			@Override
			public void widgetSelected(SelectionEvent e) {

				boolean fileFound = false;
				// loop until valid file was found
				while (!fileFound) {
					try {

						// call file dialog and set required file extension
						OpenFileDialog fileDialog = new OpenFileDialog(parent,
								Messages.OpenFileDialog_open, new String[] {
										"*.csv;*.txt;*.xml", "*.csv", "*.txt",
										"*.xml" });

						// fileDialog.isInterrupted() == Cancel button was
						// pressed
						if (!fileDialog.isInterrupted()) {

							// get path to the file and corpus and set the
							// corresponding model attributes
							filePath.setText(fileDialog.getPath());
							model = new InputModel(projectName.getText(),
									fileDialog.getPath(), fileDialog
											.getFileName());
							model.setCorpus(fileDialog.getCorpus());
							fileFound = true;

						} else
							// cancel button close loop
							fileFound = true;

					} catch (IOException e1) {
						MessageDialog.openError(parent.getShell(),
								Messages.NewProjectWizardPage_error,
								Messages.NewProjectWizardPage_couldNotOpenFile
										+ " " + e1.getLocalizedMessage());
						e1.printStackTrace();
					} catch (XMLStreamException e2) {
						MessageDialog.openError(parent.getShell(),
								Messages.NewProjectWizardPage_error,
								Messages.NewProjectWizardPage_couldNotOpenFile
										+ " " + e2.getLocalizedMessage());
						e2.printStackTrace();
					}
				}
			}
		});

	}

	/**
	 * Getter for created model.
	 * 
	 * @return Inputmodel.
	 */

	protected InputModel getModel() {
		if (model == null)
			return new InputModel();

		return model;
	}

}
